/*******************************************************************************
 * 文件名: ExcelImport.java
 * 描    述: Excel导入类
 * 创建人: Dean Huang(hudi-112@163.com)
 * 日　期: 2017-12-22
 * 描　述: 文件描述
 * 版　本: 1.0
 *******************************************************************************/

package com.z1.core.data.imports.excel;

import java.io.File;
import java.io.FileInputStream;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.z1.core.data.DataConfig;
import com.z1.core.data.DataConfigCell;
import com.z1.core.data.imports.DataImport;
import com.z1.core.exception.Z1Exception;
import com.z1.core.reflect.BeanReflect;
import com.z1.core.reflect.ObjectReflect;

public class ExcelImport extends DataImport {

	//上传文件对象
	//上传Excel对象
	private Workbook workbook = null;
	//文件读取流对象
	private FileInputStream input = null;
	
	//总上传条数
	private long sum = 0L;
	
	//上传断点
	//文档Sheet数量
	private int sumSheet = 0;
	//当前Sheet编号
	private int curSheet = 0;
	//当前Sheet读取记录
	private int sheetCur = 1;
	
	protected ExcelImport(DataConfig dataConfig, File file, boolean containHeader) {
		super(dataConfig, file, containHeader);
		try {
			//IO
			input = new FileInputStream(file);
			if (file.getName().endsWith(".xls")) {
				POIFSFileSystem fs = new POIFSFileSystem(input);
				workbook = new HSSFWorkbook(fs);
			}
			else if (file.getName().endsWith(".xlsx")) {
				OPCPackage op = OPCPackage.open(input);
				workbook = new XSSFWorkbook(op);
			}
			
			//记录总数
			//sheet数
			sumSheet = workbook.getNumberOfSheets();
			//row数
			for (int i = 0; i < sumSheet; i++) {
				int sheetRowNum = workbook.getSheetAt(i).getLastRowNum();
				sum += sheetRowNum;
			}
			if (containHeader) {
				sum -= sumSheet;
			}
		}
		catch (Exception e) {
			close();
			throw new Z1Exception(e);
		}
	}
	
	@Override
	public boolean nextData() {
		if (null == input || null == workbook) {
			return false;
		}
		try {
			valueList.clear();
			//循环读取文件中Sheet
			loop1:while (curSheet < sumSheet) {
				Sheet sheet = workbook.getSheetAt(curSheet);
				//读取指定Sheet
				for (int j = sheetCur; j <= sheet.getLastRowNum(); j++) {
					//若包含标题，跳过没Sheet第一行
					if (0 == sheetCur && containHeader) { continue; }
					//读取行
					getRow(sheet.getRow(j));
					//当前读取行数+1
					cur++;
					//当前Sheet读取行数+1
					sheetCur++;
					//若当前读取行数达到单次处理行数，跳出读取(Sheet内)
					if (0 != cur && 0 == cur % step) {
						break loop1;
					}
				}
				//若当前读取行数达到单次处理行数，跳出读取(跨Sheet)
				if (0 != cur && 0 == cur % step) {
					break;
				}
				//Sheet读取编号+1
				curSheet++;
				//当前Sheet读取行数
				sheetCur = 1;
			}
		}
		catch (Exception e) {
			throw new Z1Exception(e);
		}
		finally {
			if (cur >= sum) {
				close();
			}
		}
		return !valueList.isEmpty();
	}
	
	/**
	 * 获取行数据
	 * @param row
	 */
	private void getRow(Row row) throws Exception {
		Object value = dataConfig.getBeanClass().newInstance();
		try {
			//固定字段
			List<DataConfigCell> cells = dataConfig.getImportCells();
			for (int i = 0; i < cells.size(); i++) {
				DataConfigCell dataConfigCell = cells.get(i);
				if (null == dataConfigCell) {
					continue;
				}
				Object obj = getCell(dataConfigCell, row.getCell(i));
				if (null == obj && dataConfigCell.getRequired()) {
					//TODO: 必填参数
				}
				BeanReflect.setObjectToT(value, dataConfigCell.getProperty(), obj, dataConfigCell.getJavaTypeClass());
			}
			valueList.add(value);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取单元格数据
	 * @param type
	 * @param cell
	 * @return
	 */
	private Object getCell(DataConfigCell dataConfigCell, Cell cell) {
		try {
			if (null != cell) {
				String javaType = dataConfigCell.getJavaType();
				String value = null;
				switch (cell.getCellType()) {
					case Cell.CELL_TYPE_STRING : value = cell.getStringCellValue();break;
					case Cell.CELL_TYPE_NUMERIC :
						if (javaType.equals("java.lang.String") || javaType.equals("String")) {
							cell.setCellType(Cell.CELL_TYPE_STRING);
							value = cell.getStringCellValue();
						}
						else {
							value = String.valueOf(cell.getNumericCellValue());
						}
						break;
					case Cell.CELL_TYPE_BOOLEAN : value = cell.getBooleanCellValue() ? "0" : "1";break;
					case Cell.CELL_TYPE_FORMULA :
						if (!cell.getStringCellValue().equals("")) {
							value = cell.getStringCellValue();
						}
						else {
							value = cell.getNumericCellValue() + "";
						}
						break;
					case Cell.CELL_TYPE_BLANK :
					case Cell.CELL_TYPE_ERROR : value = "";break;
					default : value = cell.toString();
				}
				return ObjectReflect.getObject(
					dataConfigCell.getJavaType(), 
					dataConfigCell.getLength(), 
					dataConfigCell.getPrecision(), 
					value
				);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 进度(保留2为小数)
	 * @return
	 */
	@Override
	public double getSeek() {
		int seek = (int)(cur / (double)sum * 100);
		return seek/(double)100;
	}

	public static ExcelImport parse(DataConfig dataConfig, File f) {
		return new ExcelImport(dataConfig, f, true);
	}
	public static ExcelImport parse(DataConfig dataConfig, File f, boolean containHeader) {
		return new ExcelImport(dataConfig, f, containHeader);
	}

	@Override
	public void close() {
		try {
			if (null != input) {
				input.close();
				input = null;
				workbook = null;
			}
		}
		catch (Exception ex) {}
	}
	
}
